package org.wk.account.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.wk.account.dao.SubAccountDao;
import org.wk.account.dao.yuan.SubAccountYuanDao;
import org.wk.account.dao.yuan.SubAccountYuanFromZhongBillDao;
import org.wk.account.dao.yuan.SubAccountYuanSeqDao;
import org.wk.account.dao.zai.SubAccountZaiDao;
import org.wk.account.dao.zai.SubAccountZaiFromZhongBillDao;
import org.wk.account.dao.zai.SubAccountZaiSeqDao;
import org.wk.account.dao.zhong.*;
import org.wk.account.domain.SubAccount;
import org.wk.account.domain.yuan.SubAccountYuan;
import org.wk.account.domain.yuan.SubAccountYuanFromZhongBill;
import org.wk.account.domain.yuan.SubAccountYuanSeq;
import org.wk.account.domain.zai.SubAccountZai;
import org.wk.account.domain.zai.SubAccountZaiFromZhongBill;
import org.wk.account.domain.zai.SubAccountZaiSeq;
import org.wk.account.domain.zhong.*;
import org.wk.account.enums.*;
import org.wk.core.common.view.ResponseVo;
import org.wk.core.db.tool.WebUtils;
import org.wk.core.web.exception.GeneralException;
import org.wk.user.dao.UserDao;
import org.wk.user.domain.User;

import com.alibaba.fastjson.JSONObject;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
@Service
public class SubAccountZhongServiceImpl implements SubAccountZhongService {

	private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
	
	@Autowired
	private SubAccountDao subAccountDao;
	
	@Autowired
	private SubAccountZhongDao subAccountZhongDao;
	
	@Autowired
	private SubAccountZhongSeqDao subAccountZhongSeqDao;

	@Autowired
	private SubAccountZhongForOneselfBillDao subAccountZhongForOneselfBillDao;
	@Autowired
	private SubAccountZhongForOthersBillDao subAccountZhongForOthersBillDao;
	
	@Autowired
	private SubAccountZaiDao subAccountZaiDao;
	
	@Autowired
	private SubAccountZaiSeqDao subAccountZaiSeqDao;
	
	
	@Autowired
	private SubAccountZaiFromZhongBillDao subAccountZaiFromZhongBillDao;

	@Autowired
	private SubAccountYuanDao subAccountYuanDao;
	
	@Autowired
	private SubAccountYuanSeqDao subAccountYuanSeqDao;
	
	@Autowired
	private SubAccountYuanFromZhongBillDao subAccountYuanFromZhongBillDao;
	@Autowired
	private SubAccountZhongAdminUpdateBillDao subAccountZhongAdminUpdateBillDao;

	@Autowired
	private UserDao userDao;
	


	@Override
	public ResponseVo buy(JSONObject jsonObject) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ResponseVo activateOneself(JSONObject jsonObject) {
		// TODO Auto-generated method stub
		logger.info("激活自己");
		int quantity = jsonObject.getInteger("quantity");
		String userId = WebUtils.getUser().getId();
		SubAccountZhong subAccountZhong = subAccountZhongDao.findByUserId(userId);
		int preAmount = subAccountZhong.getAmount();
		// 总数与当前兑换数量校验
		if (preAmount<quantity){
			return new ResponseVo(ResponseCode.AMOUNT_DATA_ERROR);
		}
		SubAccountZhongForOneselfBill subAccountZhongForOneselfBill = new SubAccountZhongForOneselfBill();
		subAccountZhongForOneselfBill.setUserId(userId);
		subAccountZhongForOneselfBill.setAmount(quantity);
		subAccountZhongForOneselfBillDao.save(subAccountZhongForOneselfBill);
		//鲸种数量处理
		zhongHandler(userId, quantity, SeqFlag.EXPEND, ZhongChangeType.ACTIVATE_ONESELF);
		// 自己账户种鲸源与鲸仔处理
		acitivateZhong(userId,quantity,YuanChangeType.ACTIVATE_ONESELF,ZaiChangeType.ACTIVATE_ONESELF);
		JSONObject json = new JSONObject();
		json.put("date",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
		return ResponseVo.success().setData(json);
	}

	@Override
	public ResponseVo activateOthers(JSONObject jsonObject) {
		// TODO Auto-generated method stub
		logger.info("激活别人");
		int quantity = jsonObject.getIntValue("quantity");
		String mobileNumber = jsonObject.getString("mobile_number");
		String userId = WebUtils.getUser().getId();
		User user = userDao.findByMobileNumber(mobileNumber);
		if (user==null) {
			return new ResponseVo(ResponseCode.ACCOUNTS_UN_EXIST);
		}
		SubAccountZhong subAccountZhong = subAccountZhongDao.findByUserId(userId);
		int preAmount = subAccountZhong.getAmount();
		// 总数与当前兑换数量校验
		if (preAmount<quantity){
			return new ResponseVo(ResponseCode.AMOUNT_DATA_ERROR);
		}
		// 被激活用戶ID
		String receuserId = user.getId();
		SubAccountZhongForOthersBill subAccountZhongForOthersBill = new SubAccountZhongForOthersBill();
		subAccountZhongForOthersBill.setUserId(WebUtils.getUser().getId());
		subAccountZhongForOthersBill.setAmount(quantity);
		subAccountZhongForOthersBill.setForUserId(userId);
		subAccountZhongForOthersBillDao.save(subAccountZhongForOthersBill);
		//鲸种数量处理
		zhongHandler(userId, quantity, SeqFlag.EXPEND, ZhongChangeType.ACTIVATE_OTHERS);
		// 被激活人账户处理
		acitivateZhong(receuserId, quantity,YuanChangeType.OTHERS_ACTIVATE,ZaiChangeType.OTHERS_ACTIVATE);
		JSONObject json = new JSONObject();
		json.put("date",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
		return ResponseVo.success().setData(json);
	}

	@Override
	public ResponseVo zhongSeqList(JSONObject jsonObject) {
		// TODO Auto-generated method stub
		Page<SubAccountZhongSeq> subAccountZhongSeqs = subAccountZhongSeqDao.findAll(PageRequest.of(1, 10));
		ResponseVo responseVo = new ResponseVo().setData(subAccountZhongSeqs);
		return responseVo;
	}
	
	
	
	
	/**
	 * @Title		: zhongHandler
	 * @Param		: @param userId
	 * @Param		: @param quantity
	 * @Param		: @param seqFlag
	 * @Param		: @param zhongChangeType
	 * @Param		: @return
	 * @Return Type 	：boolean
	 * @Description	: 鲸种数量变动处理
	 */ 
	private boolean zhongHandler(String userId, int quantity, SeqFlag seqFlag, ZhongChangeType zhongChangeType) {
		
		SubAccountZhong subAccountZhong = subAccountZhongDao.findByUserId(userId);
		subAccountZhong = subAccountZhong==null?new SubAccountZhong():subAccountZhong;
		int preZhongAmount = subAccountZhong.getAmount();
		subAccountZhong.setAmount(preZhongAmount-quantity);
		subAccountZhong.setUserId(userId);
		subAccountZhongDao.saveOrUpdate(subAccountZhong);
		
		SubAccountZhongSeq subAccountZhongSeq = new SubAccountZhongSeq();
		subAccountZhongSeq.setUserId(userId);
		subAccountZhongSeq.setSeqFlagCode(seqFlag.getCode());
		subAccountZhongSeq.setSeqFlagName(seqFlag.getName());
		subAccountZhongSeq.setChangeTypeCode(zhongChangeType.getCode());
		subAccountZhongSeq.setChangeTypeName(zhongChangeType.getName());
		subAccountZhongSeq.setPreAmount(preZhongAmount);
		subAccountZhongSeq.setAmount(subAccountZhong.getAmount());
		subAccountZhongSeq.setChangeAmount(quantity);
		subAccountZhongSeqDao.save(subAccountZhongSeq);
		
		SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_ZHONG.getCode());
		subAccount.setAmount(new BigDecimal(subAccountZhong.getAmount()));
		subAccountDao.update(subAccount);

		return true;
	}
	
	private boolean acitivateZhong(String userId, int quantity,YuanChangeType yuanChangeType,ZaiChangeType zaiChangeType) {
		
		int zai_coefficient = 20;
		int yuan_coefficient = 80;
		
		
		int zaiNum = quantity*zai_coefficient;
		BigDecimal yuanNum = new BigDecimal(quantity*yuan_coefficient);
		/**
		 * 鲸种转鲸仔处理
		 */
		//
		SubAccountZaiFromZhongBill subAccountZaiFromZhongBill = new SubAccountZaiFromZhongBill();
		subAccountZaiFromZhongBill.setAmount(new BigDecimal(zaiNum));
		subAccountZaiFromZhongBill.setUserId(userId);
		subAccountZaiFromZhongBillDao.save(subAccountZaiFromZhongBill);
		
		SubAccountZai subAccountZai = subAccountZaiDao.findByUserId(userId);
		subAccountZai = subAccountZai==null?new SubAccountZai():subAccountZai;
		BigDecimal preZaiAmount = subAccountZai.getAmount()==null?new BigDecimal(0):subAccountZai.getAmount();
		subAccountZai.setAmount(preZaiAmount.add(new BigDecimal(zaiNum)));
		subAccountZai.setUserId(userId);
		subAccountZaiDao.saveOrUpdate(subAccountZai);
		
		SubAccountZaiSeq subAccountZaiSeq = new SubAccountZaiSeq();
		subAccountZaiSeq.setUserId(userId);
		subAccountZaiSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
		subAccountZaiSeq.setSeqFlagName(SeqFlag.INCOME.getName());
		subAccountZaiSeq.setChangeTypeCode(zaiChangeType.getCode());
		subAccountZaiSeq.setChangeTypeName(zaiChangeType.getName());
		subAccountZaiSeq.setPreAmount(preZaiAmount);
		subAccountZaiSeq.setAmount(subAccountZai.getAmount());
		subAccountZaiSeq.setChangeAmount(new BigDecimal(zaiNum));
		subAccountZaiSeqDao.save(subAccountZaiSeq);
		
		SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_ZAI.getCode());
		subAccount.setAmount(subAccountZai.getAmount());
		subAccountDao.update(subAccount);
		/**
		 * 鲸种转鲸源处理
		 */
		SubAccountYuanFromZhongBill subAccountYuanFromZhongBill = new SubAccountYuanFromZhongBill();
		subAccountYuanFromZhongBill.setAmount(yuanNum);
		subAccountYuanFromZhongBill.setUserId(userId);
		subAccountYuanFromZhongBillDao.save(subAccountYuanFromZhongBill);
		
		SubAccountYuan subAccountYuan = subAccountYuanDao.findByUserId(userId);
		subAccountYuan = subAccountYuan==null?new SubAccountYuan():subAccountYuan;
		BigDecimal preYuanAmount = subAccountYuan.getAmount();
		subAccountYuan.setAmount(preYuanAmount.add(yuanNum));
		subAccountYuan.setUserId(userId);
		subAccountYuanDao.saveOrUpdate(subAccountYuan);
		
		SubAccountYuanSeq subAccountYuanSeq = new SubAccountYuanSeq();
		subAccountYuanSeq.setUserId(userId);
		subAccountYuanSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
		subAccountYuanSeq.setSeqFlagName(SeqFlag.INCOME.getName());
		subAccountYuanSeq.setChangeTypeCode(yuanChangeType.getCode());
		subAccountYuanSeq.setChangeTypeName(yuanChangeType.getName());
		subAccountYuanSeq.setPreAmount(preYuanAmount);
		subAccountYuanSeq.setAmount(subAccountYuan.getAmount());
		subAccountYuanSeq.setChangeAmount(yuanNum);
		subAccountYuanSeqDao.save(subAccountYuanSeq);
		
		subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_YUAN.getCode());
		subAccount.setAmount(subAccountYuan.getAmount());
		subAccountDao.update(subAccount);

		return true;
	}



	@Override
	public Page<SubAccountZhongSeq> findSeqByCriteria(Integer page, Integer size, SubAccountZhongSeq subAccountZhongSeq) {
		Sort sort = Sort.by(Sort.Direction.DESC,"createTime");
		Page<SubAccountZhongSeq> zhongSeqPage = subAccountZhongSeqDao.findAll(new Specification<SubAccountZhongSeq>() {
			@Override
			public Predicate toPredicate(Root<SubAccountZhongSeq> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
				List<Predicate> list = new ArrayList<Predicate>();
				if(null!=subAccountZhongSeq.getUserId()&&!"".equals(subAccountZhongSeq.getUserId())){
					list.add(criteriaBuilder.equal(root.get("userId").as(String.class), subAccountZhongSeq.getUserId()));
				}
				Predicate[] p = new Predicate[list.size()];
				return criteriaBuilder.and(list.toArray(p));
			}
		}, PageRequest.of(page,size,sort));
		return zhongSeqPage;
	}

	@Override
	public void updateZhongAccount(BigDecimal zhong, String userId) {
		SubAccountZhong subAccountZhong = subAccountZhongDao.findByUserId(userId);
		SubAccountZhongSeq subAccountZhongSeq = new SubAccountZhongSeq();
		BigDecimal amount = new BigDecimal(subAccountZhong.getAmount());
		BigDecimal changeAmount = new BigDecimal(0);
		int num = zhong.compareTo(amount);
		if (num < 0){
			changeAmount = amount.subtract(zhong);
			subAccountZhongSeq.setSeqFlagCode(SeqFlag.EXPEND.getCode());
			subAccountZhongSeq.setSeqFlagName(SeqFlag.EXPEND.getName());
		}
		if (num > 0){
			changeAmount = zhong.subtract(amount);
			subAccountZhongSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
			subAccountZhongSeq.setSeqFlagName(SeqFlag.INCOME.getName());
		}
		if (num!=0 && zhong.compareTo(new BigDecimal(0))>=0){
			SubAccountZhongAdminUpdateBill adminUpdateBill = new SubAccountZhongAdminUpdateBill();
			adminUpdateBill.setAmount(changeAmount.intValue());
			adminUpdateBill.setUserId(userId);
			subAccountZhongAdminUpdateBillDao.save(adminUpdateBill);
			subAccountZhong.setAmount(zhong.intValue());
			subAccountZhong.setUserId(userId);
			subAccountZhongDao.saveOrUpdate(subAccountZhong);
			subAccountZhongSeq.setUserId(userId);
			subAccountZhongSeq.setChangeTypeCode(BaoChangeType.ADMIN_UPDATE.getCode());
			subAccountZhongSeq.setChangeTypeName(BaoChangeType.ADMIN_UPDATE.getName());
			subAccountZhongSeq.setPreAmount(amount.intValue());
			subAccountZhongSeq.setAmount(zhong.intValue());
			subAccountZhongSeq.setChangeAmount(changeAmount.intValue());
			subAccountZhongSeqDao.save(subAccountZhongSeq);
			SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_ZHONG.getCode());
			subAccount.setAmount(zhong);
			subAccountDao.update(subAccount);
		}
	}

	@Override
	public Page<SubAccountZhongSeq> findSeqByUserIds(int pageNum, int pageSize, List<String> userIds) {
		Sort sort = Sort.by(Sort.Direction.DESC,"createTime");
		Page<SubAccountZhongSeq> zuanSeqPage = subAccountZhongSeqDao.findAll(new Specification<SubAccountZhongSeq>() {
			@Override
			public Predicate toPredicate(Root<SubAccountZhongSeq> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
				List<Predicate> list = new ArrayList<Predicate>();
				if(!userIds.isEmpty()){
					CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("userId"));
					for (String userId:userIds){
						in.value(userId);
					}
					list.add(in);
				}
				Predicate[] p = new Predicate[list.size()];
				return criteriaBuilder.and(list.toArray(p));
			}
		}, PageRequest.of(pageNum,pageSize,sort));
		return zuanSeqPage;
	}

}
